/*
Демонстрируется Клавиатура 4x4

CodeVisionAVR C Compiler

Чип: AT90S8515
*/

/* Перед подключением файла lcd.h, объявим порт, используемый 
   для подключения модуля LCD */

#asm
  .equ __lcd_port=0x15
#endasm

/* Подключим дополнительные файлы */
#include <lcd.h>
#include <stdio.h>
#include <delay.h>
#include <90s8515.h>

// частота кварца [Гц]
#define F_XTAL 4000000L
// PIND0..3 будут входами рядов
#define KEYIN PIND
// PORTD4..7 будут выходами столбцов
#define KEYOUT PORTD

// используем для инициализации счета Таймера/Счетчика 0
#define INIT_TIMER0 TCNT1=0x100L-F_XTAL/64L/500L
#define FIRST_COLUMN 0x80
#define LAST_COLUMN 0x10

typedef unsigned char byte;

// сохраним здесь состояние каждой кнопки как бит,
// бит 0 будет KEY0, бит 1 KEY1,...
unsigned keys;
// буфер LCD дисплея
char buf[33];

// прерывание по переполнению Таймера/Счетчика 0 каждые 2 мс
interrupt [TIM0_OVF] void timer0_int(void)
{
static byte key_pressed_counter=20;
static byte column=FIRST_COLUMN;
static unsigned row_data,crt_key;

// заново инициализируем Таймер/Счетчик 0
INIT_TIMER0;
row_data<<=4;

// получим группу 4 кнопок в переменной row_data
row_data|=~KEYIN&0xf;
column>>=1;

if (column==(LAST_COLUMN>>1))
  {
  column=FIRST_COLUMN;
  if (--key_pressed_counter==9) crt_key=row_data;
  else
    {
      if (row_data!=crt_key) key_pressed_counter=10;
         else
           {
             if (!key_pressed_counter)
             {
               keys=row_data;
               key_pressed_counter=10;
             };
           };
       };
     row_data=0;
  };
// выберем следующий столбец, входы будут 
// с подтягивающими резисторами
KEYOUT=~column;
}

void init_keypad(void)
{
  DDRD=0xf0;
  KEYOUT=~FIRST_COLUMN;
  INIT_TIMER0;
  TCCR0=3;
  TIMSK=2;
  #asm("sei")
}

main() 
{
  unsigned k;
  init_keypad();
  lcd_init(16);
  lcd_putsf("CVAVR Keypad");
  
  // прочитаем кнопку и отобразим ее код
  while (1)
  {
    lcd_gotoxy(0,1);
    if (keys)
    {
      sprintf(buf,"Key code=% 04Xh",keys);
      lcd_puts(buf);
    }
    else lcd_putsf("NO KEY          ");
    delay_ms(500);
  }
}
